/*
 * Copyright (c) 2006-2025, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2025-06-18     RT-Thread    first version
 * PWM输入引脚：PA6，下拉输入
 *   过零信号输入：PA7 ，上升沿触发
 * PWM输出：100hz ，PA1 PA2
 *   功能说明：PA6输入100hz信号，转化为占空比，过零信号触发，占空比大于1 ，使能定时器通道PA1 PA2 延时10ms,进入下一次循环
 */

#include <rtthread.h>
#include "drv_common.h"
#include <rtdevice.h>
#include "stm32f1xx_hal.h"
#include "stm32f1xx_hal_tim.h"
#include <stdio.h>
#include <rtdbg.h>
#include "main.h"
#define ZERO_DET_PIN 7 //PA7
#define PWM_INPUT_PIN 6 //PA6

#define BOARD_LED_PIN 45
#define LIGHT_OUTPUT_PIN 2  //PA2
#define HEAT_OUTPUT_PIN 1 //PA1
#define IR_IN1 HAL_GPIO_ReadPin(PWM_INPUT_PIN_GPIO_Port,PWM_INPUT_PIN_Pin) //PA6

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
uint8_t current_zero_singla = 0;
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
uint8_t time_up_flag = 0; //上升沿标志位
uint8_t time_dowm_flag = 0; //下降沿标志位

uint32_t time_up_num = 0; //上升沿计数
uint32_t time_dowm_num = 0; //下降沿计数

uint32_t time_frequency; //频率
uint32_t time_duty; //占空比

static void zero_signals_turn_on(void* args)
{
    current_zero_singla = 1;

}



//CubeMX生成的TIM4中断服务函数,在stm32f1xxit.c中
void TIM2_IRQHandler(void)
{
    /* USER CODE BEGIN TIM4_IRQn 0 */
    /* USER CODE END TIM4_IRQn 0 */
    HAL_TIM_IRQHandler(&htim2);
    /* USER CODE BEGIN TIM4_IRQn 1 */
    /* USER CODE END TIM4_IRQn 1 */
}

//io外部中断信号处理
void zero_input_signal_exeute()
{
    /* PA0引脚为输入模式 */
    rt_pin_mode(ZERO_DET_PIN, PIN_MODE_INPUT_PULLUP);
    /* 绑定中断，上升沿模式，回调函数名为fire_signals_turn_on */
    rt_pin_attach_irq(ZERO_DET_PIN, PIN_IRQ_MODE_FALLING, zero_signals_turn_on, RT_NULL);
    /* 使能中断 */
    rt_pin_irq_enable(ZERO_DET_PIN, PIN_IRQ_ENABLE);
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{

}
/* USER CODE BEGIN 4 */
// 捕获中断回调函数，每次捕获到信号就会进入这个回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{

    if (htim == &htim3)
    {
        if (IR_IN1 && time_up_flag == 0) //第一次上升
        {

            time_up_flag = 1;
            __HAL_TIM_SET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); // 改变捕获极性为下降沿捕获
            __HAL_TIM_SET_COUNTER(&htim3, 0); // 计数清零，从头开始计

        }
        else if (IR_IN1 == 0 && time_dowm_flag == 0) //下降
        {

            time_dowm_num = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); // 读取捕获计数，这个时间即为上升沿持续的时间
            __HAL_TIM_SET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING); // 改变捕获极性为上升沿沿捕获
            time_dowm_flag = 1;
        }
        else if (IR_IN1 && time_dowm_flag == 1) //第二次之后上升
        {
            time_up_num = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); // 读取捕获计数，这个时间即为上升沿持续的时间
            __HAL_TIM_SET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); // 改变捕获极性为下降沿捕获
            time_dowm_flag = 0;
            __HAL_TIM_SET_COUNTER(&htim3, 0); // 计数清零，从头开始计

        }
    }

}/**


 /**
 * @brief TIM2 Initialization Function
 * @param None
 * @retval None
 */
static void MX_TIM2_Init(void)
{

    /* USER CODE BEGIN TIM2_Init 0 */

    /* USER CODE END TIM2_Init 0 */

    TIM_ClockConfigTypeDef sClockSourceConfig = { 0 };
    TIM_MasterConfigTypeDef sMasterConfig = { 0 };

    /* USER CODE BEGIN TIM2_Init 1 */

    /* USER CODE END TIM2_Init 1 */
    htim2.Instance = TIM2;
    htim2.Init.Prescaler = 720 - 1;
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = 10000 -1;
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
    {
        Error_Handler();
    }
    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
    if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
    {
        Error_Handler();
    }
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
    {
        Error_Handler();
    }
    /* USER CODE BEGIN TIM2_Init 2 */

    /* USER CODE END TIM2_Init 2 */

}

/**
 * @brief TIM3 Initialization Function
 * @param None
 * @retval None
 */
static void MX_TIM3_Init(void)
{

    /* USER CODE BEGIN TIM3_Init 0 */

    /* USER CODE END TIM3_Init 0 */

    TIM_MasterConfigTypeDef sMasterConfig = { 0 };
    TIM_IC_InitTypeDef sConfigIC = { 0 };

    /* USER CODE BEGIN TIM3_Init 1 */

    /* USER CODE END TIM3_Init 1 */
    htim3.Instance = TIM3;
    htim3.Init.Prescaler = 720 - 1;
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim3.Init.Period = 65535;
    htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    if (HAL_TIM_IC_Init(&htim3) != HAL_OK)
    {
        Error_Handler();
    }
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
    {
        Error_Handler();
    }
    sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
    sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
    sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
    sConfigIC.ICFilter = 0;
    if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
    {
        Error_Handler();
    }
    /* USER CODE BEGIN TIM3_Init 2 */

    /* USER CODE END TIM3_Init 2 */

}

/**
 * @brief GPIO Initialization Function
 * @param None
 * @retval None
 */
static void MX_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = { 0 };
    /* USER CODE BEGIN MX_GPIO_Init_1 */

    /* USER CODE END MX_GPIO_Init_1 */

    /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOC_CLK_ENABLE()
    ;
    __HAL_RCC_GPIOD_CLK_ENABLE()
    ;
    __HAL_RCC_GPIOA_CLK_ENABLE()
    ;

    /*Configure GPIO pin Output Level */
    HAL_GPIO_WritePin(BOARD_LED_PIN_GPIO_Port, BOARD_LED_PIN_Pin, GPIO_PIN_RESET);

    /*Configure GPIO pin Output Level */
    HAL_GPIO_WritePin(GPIOA, HEAT_OUTPUT_PIN_1_Pin | HEAT_OUTPUT_PIN_2_Pin, GPIO_PIN_RESET);

    /*Configure GPIO pin : BOARD_LED_PIN_Pin */
    GPIO_InitStruct.Pin = BOARD_LED_PIN_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(BOARD_LED_PIN_GPIO_Port, &GPIO_InitStruct);

    /*Configure GPIO pins : HEAT_OUTPUT_PIN_1_Pin HEAT_OUTPUT_PIN_2_Pin */
    GPIO_InitStruct.Pin = HEAT_OUTPUT_PIN_1_Pin | HEAT_OUTPUT_PIN_2_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /*Configure GPIO pin : ZERO_DET_PIN_Pin */
    GPIO_InitStruct.Pin = ZERO_DET_PIN_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(ZERO_DET_PIN_GPIO_Port, &GPIO_InitStruct);

    /* USER CODE BEGIN MX_GPIO_Init_2 */

    /* USER CODE END MX_GPIO_Init_2 */
}

/**
 * @brief This function handles TIM3 global interrupt.
 */
void TIM3_IRQHandler(void)
{
    /* USER CODE BEGIN TIM3_IRQn 0 */

    /* USER CODE END TIM3_IRQn 0 */
    HAL_TIM_IRQHandler(&htim3);
    /* USER CODE BEGIN TIM3_IRQn 1 */

    /* USER CODE END TIM3_IRQn 1 */
}


int main(void)
{
    MX_GPIO_Init();
    rt_kprintf("CrossZeroDetection...");

    //io输出
    rt_pin_mode(BOARD_LED_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(HEAT_OUTPUT_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LIGHT_OUTPUT_PIN, PIN_MODE_OUTPUT);
    rt_pin_write(LIGHT_OUTPUT_PIN, PIN_HIGH);
    rt_pin_write(HEAT_OUTPUT_PIN, PIN_HIGH);
    rt_pin_write(BOARD_LED_PIN, PIN_HIGH);

    MX_TIM3_Init();
    rt_thread_mdelay(5000);
    //io中断
    zero_input_signal_exeute();

    HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);   //开启TIM3的捕获通道1，并且开启捕获中断
    __HAL_TIM_ENABLE_IT(&htim3, TIM_IT_UPDATE);   //使能更新中断
    HAL_TIM_Base_Start_IT(&htim3); //使能定时器，更新中断


    uint16_t all_delay_time_us = 10000;

    while (1)
    {

        time_frequency = 100000 / time_up_num; //频率
        float down_num = (float) time_dowm_num;
        float up_num = (float) time_up_num;
        float duty = down_num / up_num; //占空比
        time_duty = duty * 100.0f;
        if (time_dowm_num == 0 || time_up_num == 0)
        {
            time_frequency = 0;
            time_duty = 0;
        }

        //延时多少微妙后打开
        uint32_t delay_open_us = (all_delay_time_us - (all_delay_time_us * time_duty / 100.0f));

        rt_kprintf("\ntime_frequency=%d,time_duty=%u current_zero_singla=%u,time_dowm_num = %u delay_time =%u\n",
                (int) time_frequency, time_duty, current_zero_singla,  delay_open_us);

        if (current_zero_singla == 1 && time_duty >= 1 && time_duty <= 100)
        {
            //延时
            rt_hw_us_delay(delay_open_us);
            //输出
            rt_pin_write(BOARD_LED_PIN, PIN_LOW);
            rt_pin_write(LIGHT_OUTPUT_PIN, PIN_LOW);
            rt_pin_write(HEAT_OUTPUT_PIN, PIN_LOW);
            current_zero_singla = 0;

            //延时
            rt_hw_us_delay(50);
            //关闭

            rt_pin_write(BOARD_LED_PIN, PIN_HIGH);
            rt_pin_write(LIGHT_OUTPUT_PIN, PIN_HIGH);
            rt_pin_write(HEAT_OUTPUT_PIN, PIN_HIGH);

        }
        rt_thread_mdelay(1);
    }

    return RT_EOK;
}
